#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;

// <property_definition> ~ <property_mods> <data_type> <property_name>  {public, protected, private, static, abstract, override, virtual, final, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
void Parser::Parse_PropertyDefinition(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyDefinition");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {public, protected, private, static, abstract, override, virtual, final, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
	if(	currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordPublic || 
		currentUnit.subtype == KeywordProtected || currentUnit.subtype == KeywordPrivate || 
		currentUnit.subtype == KeywordStatic || currentUnit.subtype == KeywordAbstract || 
		currentUnit.subtype == KeywordOverride || currentUnit.subtype == KeywordVirtual || 
		currentUnit.subtype == KeywordFinal || currentUnit.subtype == KeywordInt || 
		currentUnit.subtype == KeywordFloat || currentUnit.subtype == KeywordBool || 
		currentUnit.subtype == KeywordState || currentUnit.subtype == KeywordTime || 
		currentUnit.subtype == KeywordVoid || currentUnit.subtype == KeywordFacility || 
		currentUnit.subtype == KeywordStorage || currentUnit.subtype == KeywordQueue || 
		currentUnit.subtype == KeywordADTable || currentUnit.subtype == KeywordGroup || 
		currentUnit.subtype == KeywordOutputStream) || currentUnit.type == LUTypeIdentifier)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyDefinition__PropertyMods_DataType_PropertyName;

		// process nonterminal symbol <property_mods> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_PropertyMods(newNode0);

		// process nonterminal symbol <data_type> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_DataType(newNode1);

		// process nonterminal symbol <property_name> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_PropertyName(newNode2);

	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_DEFINITION_BEGINING);
		// This is recovoring from error
        this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyDefinition");
#endif
}

// <property_mods> ~ <property_mod> <property_mods>  {public, protected, private, static, abstract, override, virtual, final}
// <property_mods> ~ ? {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
void Parser::Parse_PropertyMods(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyMods");
#endif
	LexicUnit currentUnit;
	do{
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// if current lexic unit is in the select set of {public, protected, private, static, abstract, override, virtual, final}
		if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordPublic || 
		currentUnit.subtype == KeywordProtected || currentUnit.subtype == KeywordPrivate || 
		currentUnit.subtype == KeywordStatic || currentUnit.subtype == KeywordAbstract || 
		currentUnit.subtype == KeywordOverride || currentUnit.subtype == KeywordVirtual || 
		currentUnit.subtype == KeywordFinal))
		{
			// write type of production in this node
			parent->Production =Gr_PropertyMods__PropertyMod_PropertyMods;

			// process nonterminal symbol <property_mod> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_PropertyMod(newNode0);
		}
		// if current lexic unit is in the select set of {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
		else if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordInt || 
		currentUnit.subtype == KeywordFloat || currentUnit.subtype == KeywordBool || 
		currentUnit.subtype == KeywordState || currentUnit.subtype == KeywordTime || 
		currentUnit.subtype == KeywordVoid || currentUnit.subtype == KeywordFacility || 
		currentUnit.subtype == KeywordStorage || currentUnit.subtype == KeywordQueue || 
		currentUnit.subtype == KeywordADTable || currentUnit.subtype == KeywordGroup || 
		currentUnit.subtype == KeywordOutputStream) || currentUnit.type == LUTypeIdentifier)
		{
			// write type of production in this node
			parent->Production =Gr_PropertyMods__PropertyMod_PropertyMods;
			// new node is not needed
			break;
		}


		else
		{
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_MODS_BEGINING);
			// MAKE LOGICAL RECOVERING
			this->CurrentLexicPosition++;
			break;
		}
	}while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyMods");
#endif
}

// <property_mod> ~ public  {public}
// <property_mod> ~ protected  {protected}
// <property_mod> ~ private  {private}
// <property_mod> ~ static  {static}
// <property_mod> ~ abstract  {abstract}
// <property_mod> ~ override  {override}
// <property_mod> ~ virtual  {virtual}
// <property_mod> ~ final  {final}
void Parser::Parse_PropertyMod(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyMod");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {public}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordPublic)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__public;

		// process terminal symbol 'public' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {protected}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordProtected)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__protected;

		// process terminal symbol 'protected' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {private}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordPrivate)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__private;

		// process terminal symbol 'private' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {static}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordStatic)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__static;

		// process terminal symbol 'static' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {abstract}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAbstract)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__abstract;

		// process terminal symbol 'abstract' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {override}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOverride)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__override;

		// process terminal symbol 'override' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {virtual}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordVirtual)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__virtual;

		// process terminal symbol 'virtual' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {final}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordFinal)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyMod__final;

		// process terminal symbol 'final' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_MOD_BEGINING);
		// This is recovoring from error
        this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyMod");
#endif
}


// <property_name> ~ NAME <prop_array_defs> <property_body>  {NAME}
void Parser::Parse_PropertyName(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyName");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {NAME}
	if(currentUnit.type == LUTypeIdentifier)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyName__NAME_PropArrayDefs_PropertyBody;

		// process terminal symbol 'NAME' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

		// process nonterminal symbol <prop_array_defs> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_PropArrayDefs(newNode1);

		// process nonterminal symbol <property_body> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_PropertyBody(newNode2);

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_NAME_BEGINING);
		// This is recovoring from error
        this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyName");
#endif
}

//<prop_array_defs> ~ <prop_array_def> <prop_array_defs>  {[}
//<prop_array_defs> ~ ? {{, }, write, read}
void Parser::Parse_PropArrayDefs(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropArrayDefs");
#endif
	LexicUnit currentUnit;
	do{
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// if current lexic unit is in the select set of {[}
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftSquareBracket)
		{
			// write type of production in this node
			parent->Production =Gr_PropArrayDefs__PropArrayDef_PropArrayDefs;
	

			// process nonterminal symbol <prop_array_def> 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			Parse_PropArrayDef(newNode1);
		
		}
		// if current lexic unit is in the select set of {{, }, write, read}
		else if(currentUnit.type == LUTypeSpecialCharacter && (currentUnit.subtype == SpecialCharacterLeftCurlyBrace ||	
			currentUnit.subtype == SpecialCharacterRightCurlyBrace) || currentUnit.type == LUTypeKeyword && 
			(currentUnit.subtype == KeywordWrite || currentUnit.subtype == KeywordRead))
		{
			// write type of production in this node
			parent->Production =Gr_PropArrayDefs__PropArrayDef_PropArrayDefs;
			// new node is not needed
			break;

		}
		else
		{
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROP_ARRAY_DEFS_BEGINING);
			// MAKE LOGICAL RECOVERING
			this->CurrentLexicPosition++;
			break;
		}
	}while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropArrayDefs");
#endif
}

// <prop_array_def> ~ [ int NAME ]  {[}
void Parser::Parse_PropArrayDef(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropArrayDef");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {[}
	if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftSquareBracket)
	{
		// write type of production in this node
		parent->Production =Gr_PropArrayDef__spLSBrac_int_NAME_spRSBrac;

		// process terminal symbol '[' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'int' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInt  )
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INT_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol 'NAME' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeIdentifier)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol ']' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightSquareBracket)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_SQUARE_BRACKET_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROP_ARRAY_DEF_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropArrayDef");
#endif
}

// <property_body> ~ { <property_read> <property_write> }  {{}
// <property_body> ~ { <property_write> <property_read> }  {{}
void Parser::Parse_PropertyBody(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyBody");
#endif
	LexicUnit currentUnit;
	LexicUnit nextUnit;

	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// get the next lexic unit to solve the ambiguity
	nextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition+1);
	// if current lexic unit is in the select set of {{} and if next lexic unit is the keyword 'read',
	// because of the ambiguity
	if((currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace) &&
		(nextUnit.type == LUTypeKeyword && nextUnit.subtype == KeywordRead))
	{
		// write type of production in this node
		parent->Production =Gr_PropertyBody__spLCBrac_PropertyRead_PropertyWrite_spRCBrac;

		// process terminal symbol '{' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <property_read> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_PropertyRead(newNode1);

		// process nonterminal symbol <property_write> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_PropertyWrite(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	// if current lexic unit is in the select set of {{} and if next lexic unit is the keyword 'write',
	// because of the ambiguity
	else if((currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace) &&
		(nextUnit.type == LUTypeKeyword && nextUnit.subtype == KeywordWrite))
	{
		// write type of production in this node
		parent->Production =Gr_PropertyBody__spLCBrac_PropertyWrite_PropertyRead_spRCBrac;

		// process terminal symbol '{' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <property_write> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_PropertyWrite(newNode1);

		// process nonterminal symbol <property_read> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_PropertyRead(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_BODY_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyBody");
#endif
}

// <property_read> ~ read { <method_body> }  {read}
// <property_read> ~ ? {write, }}
void Parser::Parse_PropertyRead(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyRead");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {read}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRead)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyRead__read_spLCBrac_MethodBody_spRCBrac;

		// process terminal symbol 'read' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <method_body> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_MethodBody(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	// if current lexic unit is in the select set of {write, }}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWrite || 
		currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyRead__epsilon;

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_READ_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyRead");
#endif
}

// <property_write> ~ write { <method_body> }  {write}
// <property_write> ~ ? {}, read}
void Parser::Parse_PropertyWrite(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PropertyWrite");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {write}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWrite)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyWrite__write_spLCBrac_MethodBody_spRCBrac;

		// process terminal symbol 'write' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <method_body> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_MethodBody(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	// if current lexic unit is in the select set of {}, read}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRead || 
		currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
	{
		// write type of production in this node
		parent->Production =Gr_PropertyWrite__epsilon;

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROPERTY_WRITE_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PropertyWrite");
#endif
}

// <method_definition> ~ <method_mods> <start_process> <data_type> NAME ( <parameters> ) <method_body_decl>  {abstract, virtual, public, private, protected, override, static, final, start, process, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
// <method_definition> ~ <method_mods> numeric <numeric_mod> <data_type> NAME ( <parameters>> ) { <inf_begin> <value_pairs> <inf_end> }  {abstract, virtual, public, private, protected, override, static, final, numeric}
void Parser::Parse_MethodDefinition(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_MethodDefinition");
#endif
	LexicUnit currentUnit;
	//LexicUnit nextUnit;

	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordPublic || 
		currentUnit.subtype == KeywordProtected || currentUnit.subtype == KeywordPrivate || 
		currentUnit.subtype == KeywordStatic || currentUnit.subtype == KeywordAbstract || 
		currentUnit.subtype == KeywordOverride || currentUnit.subtype == KeywordVirtual || 
		currentUnit.subtype == KeywordFinal || currentUnit.subtype == KeywordInt || 
		currentUnit.subtype == KeywordFloat || currentUnit.subtype == KeywordBool || 
		currentUnit.subtype == KeywordState || currentUnit.subtype == KeywordTime || 
		currentUnit.subtype == KeywordVoid || currentUnit.subtype == KeywordFacility || 
		currentUnit.subtype == KeywordStorage || currentUnit.subtype == KeywordQueue || 
		currentUnit.subtype == KeywordADTable || currentUnit.subtype == KeywordGroup || 
		currentUnit.subtype == KeywordStart || currentUnit.subtype == KeywordProcess || 
		currentUnit.subtype == KeywordOutputStream || currentUnit.subtype == KeywordNumeric) || 
		currentUnit.type == LUTypeIdentifier)
	{
		// process nonterminal symbol <method_mods> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_MethodMods(newNode0);


		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNumeric){
			// write type of production in this node
			parent->Production =Gr_MethodDefinition__MethodMods_numeric_NumericMod_DataType_NAME_spLPar_Parameters_spRPar_spLCBrac_InfBegin_ValuePairs_InfEnd_spRCBrac;

			// process terminal symbol 'numeric' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNumeric)
			{
				SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode1);
				newNode1->LexUnitID=this->CurrentLexicPosition;
				newNode1->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NUMERIC_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process nonterminal symbol <numeric_mod> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_NumericMod(newNode2);

			// process nonterminal symbol <data_type> 
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			Parse_DataType(newNode3);

			// process terminal symbol 'NAME' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeIdentifier)
			{
				SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode4);
				newNode4->LexUnitID=this->CurrentLexicPosition;
				newNode4->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process terminal symbol '(' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
			{
				SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode5);
				newNode5->LexUnitID=this->CurrentLexicPosition;
				newNode5->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process nonterminal symbol <parameters> 
			SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode6);
			Parse_Parameters(newNode6);

			// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
			{
				SyntaxTreeNode * newNode7 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode7);
				newNode7->LexUnitID=this->CurrentLexicPosition;
				newNode7->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
	
			// process terminal symbol '{' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
			{
				SyntaxTreeNode * newNode8 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode8);
				newNode8->LexUnitID=this->CurrentLexicPosition;
				newNode8->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
	
			// process nonterminal symbol <inf_begin> 
			SyntaxTreeNode * newNode9 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode9);
			Parse_InfBegin(newNode9);

			// process nonterminal symbol <value_pairs> 
			SyntaxTreeNode * newNode10 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode10);
			Parse_ValuePairs(newNode10);

			// process nonterminal symbol <inf_end> 
			SyntaxTreeNode * newNode11 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode11);
			Parse_InfEnd(newNode11);
		
			// process terminal symbol '}' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
			{
				SyntaxTreeNode * newNode12 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode12);
				newNode12->LexUnitID=this->CurrentLexicPosition;
				newNode12->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
		}

		else if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordInt || 
			currentUnit.subtype == KeywordFloat || currentUnit.subtype == KeywordBool || 
			currentUnit.subtype == KeywordState || currentUnit.subtype == KeywordTime || 
			currentUnit.subtype == KeywordVoid || currentUnit.subtype == KeywordFacility || 
			currentUnit.subtype == KeywordStorage || currentUnit.subtype == KeywordQueue || 
			currentUnit.subtype == KeywordADTable || currentUnit.subtype == KeywordGroup || 
			currentUnit.subtype == KeywordStart || currentUnit.subtype == KeywordProcess || 
			currentUnit.subtype == KeywordOutputStream) || currentUnit.type == LUTypeIdentifier)
		{
			// write type of production in this node
			parent->Production =Gr_MethodDefinition__MethodMods_StartProcess_DataType_NAME_spLPar_Parameters_spRPar_MethodBodyDecl;
	
			// process nonterminal symbol <start_process> 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			Parse_StartProcess(newNode1);
		
			// process nonterminal symbol <data_type> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_DataType(newNode2);

			// process terminal symbol 'NAME' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if( currentUnit.type == LUTypeIdentifier)
				{
				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				newNode3->LexUnitID=this->CurrentLexicPosition;
				newNode3->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process terminal symbol '(' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis )
			{
				SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode4);
				newNode4->LexUnitID=this->CurrentLexicPosition;
				newNode4->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

			// process nonterminal symbol <parameters> 
			SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode5);
			Parse_Parameters(newNode5);
	
			// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis )
			{
				SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode6);
				newNode6->LexUnitID=this->CurrentLexicPosition;
				newNode6->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
	
			// process nonterminal symbol <method_body_decl> 
			SyntaxTreeNode * newNode7 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode7);
			Parse_MethodBodyDecl(newNode7);

		}
		else
		{
			// ERROR has been found
			// REPORT ERROR
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_METHOD_DEFINITION_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;

	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_MethodDefinition");
#endif
}


// <method_mods> ~ <method_mod> <method_mods>  {abstract, virtual, public, private, protected, override, static, final}
// <method_mods> ~ ? {start, process, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, numeric}
void Parser::Parse_MethodMods(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_MethodMods");
#endif
	LexicUnit currentUnit;
	do{
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// if current lexic unit is in the select set of {abstract, virtual, public, private, protected, override, static, final}
		if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordAbstract || 
			currentUnit.subtype == KeywordVirtual || currentUnit.subtype == KeywordPublic || 
			currentUnit.subtype == KeywordPrivate || currentUnit.subtype == KeywordProtected || 
			currentUnit.subtype == KeywordOverride || currentUnit.subtype == KeywordStatic || 
			currentUnit.subtype == KeywordFinal))
		{
			// write type of production in this node
			parent->Production =Gr_MethodMods__MethodMod_MethodMods;

			// process nonterminal symbol <method_mod> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_MethodMod(newNode0);
		}
		// if current lexic unit is in the select set of {start, process, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, numeric}
		else if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordStart || 
			currentUnit.subtype == KeywordProcess || currentUnit.subtype == KeywordInt || 
			currentUnit.subtype == KeywordFloat || currentUnit.subtype == KeywordBool || 
			currentUnit.subtype == KeywordState || currentUnit.subtype == KeywordTime || 
			currentUnit.subtype == KeywordVoid || currentUnit.subtype == KeywordFacility || 
			currentUnit.subtype == KeywordStorage || currentUnit.subtype == KeywordQueue ||
			currentUnit.subtype == KeywordADTable || currentUnit.subtype == KeywordGroup ||
			currentUnit.subtype == KeywordOutputStream || currentUnit.subtype == KeywordNumeric) 
			|| currentUnit.type == LUTypeIdentifier)
		{
			// write type of production in this node
			parent->Production =Gr_MethodMods__MethodMod_MethodMods;
			break;
	
		}
		else
		{
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_METHOD_MODS_BEGINING);
			// MAKE LOGICAL RECOVERING
			this->CurrentLexicPosition++;
			break;
		}
	}while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_MethodMods");
#endif
}

// <method_mod> ~ abstract  {abstract}
// <method_mod> ~ virtual  {virtual}
// <method_mod> ~ public  {public}
// <method_mod> ~ private  {private}
// <method_mod> ~ protected  {protected}
// <method_mod> ~ override  {override}
// <method_mod> ~ static  {static}
// <method_mod> ~ final  {final}
void Parser::Parse_MethodMod(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_MethodMod");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {abstract}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAbstract)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__abstract;

		// process terminal symbol 'abstract' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {virtual}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordVirtual)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__virtual;

		// process terminal symbol 'virtual' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {public}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordPublic)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__public;

		// process terminal symbol 'public' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {private}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordPrivate)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__private;

		// process terminal symbol 'private' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {protected}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordProtected)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__protected;

		// process terminal symbol 'protected' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {override}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOverride)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__override;

		// process terminal symbol 'override' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {static}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordStatic)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__static;

		// process terminal symbol 'static' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {final}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordFinal)
	{
		// write type of production in this node
		parent->Production =Gr_MethodMod__final;

		// process terminal symbol 'final' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_METHOD_MOD_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_MethodMod");
#endif
}


// <start_process> ~ start process  {start}
// <start_process> ~ process  {process}
// <start_process> ~ ? {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
void Parser::Parse_StartProcess(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_StartProcess");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {start}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordStart)
	{
		// write type of production in this node
		parent->Production =Gr_StartProcess__start_process;

		// process terminal symbol 'start' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

		// process terminal symbol 'process' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordProcess)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PROCESS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	// if current lexic unit is in the select set of {process}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordProcess)
	{
		// write type of production in this node
		parent->Production =Gr_StartProcess__process;

		// process terminal symbol 'process' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
	else if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat || currentUnit.subtype == KeywordBool ||
		currentUnit.subtype == KeywordState || currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid || currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage || currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable || currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordOutputStream) || currentUnit.type == LUTypeIdentifier)
	{
		// write type of production in this node
		parent->Production =Gr_StartProcess__epsilon;

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_START_PROCESS_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_StartProcess");
#endif
}




